<template>
  <div class="speech-cn-container">
    <button @click="collect('prevBtn', '上一张')" :disabled="prevBtnDisabled">
      上一张
    </button>
    <button @click="collect('nextBtn', '下一张')" :disabled="nextBtnDisabled">
      下一张
    </button>
    <button
      @click="collect('otherBtn', '背景噪音')"
      :disabled="otherBtnDisabled"
    >
      背景噪音
    </button>
    <button @click="save">保存</button>
    <button @click="train">训练</button>
    监听开关：<input type="checkbox" v-model="isListen" @change="toggle" />
    <pre id="count"></pre>
  </div>
</template>

<script>
import { reactive, toRefs } from "vue";
import * as speechCommands from "@tensorflow-models/speech-commands";
import * as tfvis from "@tensorflow/tfjs-vis";

const MODEL_PATH = "http://127.0.0.1:8080";

export default {
  setup: async function () {
    const state = reactive({
      labels: [],
      prevBtnDisabled: false,
      nextBtnDisabled: false,
      otherBtnDisabled: false,
      current: "",
      isListen: false,
    });

    const recognizer = speechCommands.create(
      "BROWSER_FFT",
      null,
      MODEL_PATH + "/speech/model.json",
      MODEL_PATH + "/speech/metadata.json"
    );
    await recognizer.ensureModelLoaded();
    const transferRecognizer = recognizer.createTransfer("轮播图");

    // 收集
    async function collect(type, label) {
      state[`${type}Disabled`] = true;
      await transferRecognizer.collectExample(
        label === "背景噪音" ? "_background_noise_" : label
      );
      state[`${type}Disabled`] = false;
      document.querySelector("#count").innerHTML = JSON.stringify(
        transferRecognizer.countExamples(),
        null,
        2
      );
    }

    // 训练
    async function train() {
      await transferRecognizer.train({
        epochs: 30,
        callback: tfvis.show.fitCallbacks(
          { name: "训练效果" },
          ["loss", "acc"],
          { callbacks: ["onEpochEnd"] }
        ),
      });
    }

    //切换
    async function toggle() {
      if (state.isListen) {
        await transferRecognizer.listen(
          (result) => {
            const { scores } = result;
            const labels = transferRecognizer.wordLabels();
            const index = scores.indexOf(Math.max(...scores));
            const current = labels[index];
            state.current = current;
            console.log(current);
          },
          {
            overlapFactor: 0,
            probabilityThreshold: 0.8,
          }
        );
      } else {
        transferRecognizer.stopListening();
      }
    }

    // 保存
     function save() {
      const arrayBuffer = transferRecognizer.serializeExamples();
      const blob = new Blob([arrayBuffer]);
      const link = document.createElement("a");
      link.href = window.URL.createObjectURL(blob);
      link.download = "data.bin";
      link.click();
    }

    return {
      ...toRefs(state),
      collect,
      train,
      toggle,
      save,
    };
  },
};
</script>

<style lang="scss" scoped>
.speech-cn-container {
  button {
    margin-right: 10px;
  }
}
</style>